/*
 * EC (Embedded Controller) for EA Loongson3 platform
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include <sys/io.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <stdlib.h>
#include <string.h>

#include "win_menu.h"

#include <ncurses.h>
#include <menu.h>

#include <ec_it8528.h>

/* This spinlock is dedicated for 62&66 ports and super io port access. */

static int send_ec_command(unsigned char command)
{
	int timeout, ret = 0;

	timeout = EC_SEND_TIMEOUT;
	while ((inb(EC_STS_PORT) & EC_IBF) && --timeout)
		;
	if (!timeout) {
		printf( "Timeout while sending command 0x%02x to EC!\n", command);
		ret = -1;
		goto out;
	}

	outb(command, EC_CMD_PORT);

out:
	return ret;
}

static int send_ec_data(unsigned char data)
{
	int timeout, ret = 0;

	timeout = EC_SEND_TIMEOUT;
	while ((inb(EC_STS_PORT) & EC_IBF) && --timeout)
		;
	if (!timeout) {
		printf( "Timeout while sending data 0x%02x to EC!\n", data);
		ret = -1;
		goto out;
	}

	outb(data, EC_DAT_PORT);

out:
	return ret;
}

static unsigned char recv_ec_data(void)
{
	int timeout;
	unsigned char data;

	timeout = EC_RECV_TIMEOUT;
	while (!(inb(EC_STS_PORT) & EC_OBF) && --timeout)
		;
	if (!timeout) {
		printf( "Timeout while receiving data from EC! status 0x%x.\n", inb(EC_STS_PORT));
		data = 0;
		goto skip_data;
	}

	data = inb(EC_DAT_PORT);

skip_data:
	return data;
}

void clean_it8528_event_status(void)
{
	unsigned long flags;

	outl(0x404000, 0x810);
}

unsigned char it8528_read(unsigned char index)
{
	unsigned char value = 0;
	unsigned long flags;
	int ret = 0;

	ret = send_ec_command(CMD_READ_EC);
	if (ret < 0) {
		printf( "Send command fail!\n");
		value = 0;
		goto out;
	}
	ret = send_ec_data(index);
	if (ret < 0) {
		printf( "Send data fail!\n");
		value = 0;
		goto out;
	}
	value = recv_ec_data();
out:

	return value;
}

unsigned char it8528_read_all(unsigned char command, unsigned char index)
{
	unsigned char value = 0;
	unsigned long flags;
	int ret = 0;

	ret = send_ec_command(command);
	if (ret < 0) {
		printf( "Send command fail!\n");
		goto out;
	}
	ret = send_ec_data(index);
	if (ret < 0) {
		printf( "Send data fail!\n");
		goto out;
	}
	value = recv_ec_data();
out:

	return value;
}

unsigned char it8528_read_noindex(unsigned char command)
{
	unsigned char value = 0;
	unsigned long flags;
	int ret = 0;

	ret = send_ec_command(command);
	if (ret < 0) {
		printf( "Send command fail!\n");
		goto out;
	}
	value = recv_ec_data();
out:

	return value;
}

int it8528_write(unsigned char index, unsigned char data)
{
	int ret = 0;
	unsigned long flags;

	ret = send_ec_command(CMD_WRITE_EC);
	if (ret < 0) {
		printf( "Send command 0x81 fail!\n");
		goto out;
	}
	ret = send_ec_data(index);
	if (ret < 0) {
		printf( "Send index 0x%x fail!\n", index);
		goto out;
	}

	ret = send_ec_data(data);
	if (ret < 0) {
		printf( "Send data 0x%x fail!\n", data);
	}
out:

	return ret;
}

int it8528_write_all(unsigned char command, unsigned char index, unsigned char data)
{
	unsigned long flags;

	send_ec_command(command);
	send_ec_data(index);
	send_ec_data(data);

	return 0;
}

int it8528_write_noindex(unsigned char command, unsigned char data)
{
	unsigned long flags;

	send_ec_command(command);
	send_ec_data(data);

	return 0;
}

int it8528_query_get_event_num(void)
{
	unsigned char value = 0;
	unsigned long flags;
	int ret = 0;
	unsigned int timeout;

	ret = send_ec_command(CMD_GET_EVENT_NUM);
	if (ret < 0) {
		printf( "Send command fail!\n");
		goto out;
	}

	/* check if the command is received by ec */
	timeout = EC_CMD_TIMEOUT;
	while ((inb(EC_STS_PORT) & EC_IBF) && timeout--)
		;
	if (timeout <= 0) {
		printf( "EC QUERY SEQ: deadable error : timeout...\n");
		ret = -1;
		goto out;
	}

	value = recv_ec_data();
out:

	return value;
}
